package com.jungle;

import com.jungle.task.CompensableTaskDispatcher;
import com.jungle.task.Task;
import com.jungle.task.TaskDispatcher;
import com.jungle.task.executor.InsertTaskExecutor;
import com.jungle.task.executor.TaskExecutor;
import com.jungle.task.parameter.*;
import com.jungle.task.result.*;

import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * @author 李岩 at 2021/10/22.
 */
public class FscContext {

    private final TaskDispatcher taskDispatcher;

    public FscContext(final List<TaskExecutor<?,?>> executors, final boolean enableCompensate){
        if (enableCompensate) {
            this.taskDispatcher = new CompensableTaskDispatcher(executors);
        }else {
            this.taskDispatcher = new TaskDispatcher(executors);
        }

    }


    public <T extends TaskParameter ,V extends TaskResult> TaskResult publishTask(final Task<T,V> task){
        if (Objects.isNull(task) || Objects.isNull(task.getTaskType())){
            return null;
        }

        task.setResult(Optional.ofNullable(task.getResult()).orElseGet(HashMap::new));
        task.setComplete(false);

        try {
            switch (task.getTaskType()) {
                case CONVERT:
                    return this.taskDispatcher.dispatchConvertTask((Task<ConvertTaskParameter, ConvertTaskResult>)task);
                case INSERT:
                    this.taskDispatcher.dispatchSaveTask((Task<SaveTaskParameter, SaveTaskResult>)task);
                    return null;
                case QUERY:
                    return this.taskDispatcher.dispatchQueryTask((Task<QueryTaskParameter, QueryTaskResult>)task);
                case COMPENSATE:
                    return this.taskDispatcher.dispatchCompensateTask((Task<CompensateTaskParameter, CompensateTaskResult>)task);
                default:
                    return null;
            }
        }finally {
            task.setComplete(true);
        }
    }

    public void publishTask(final Task<SaveTaskParameter, SaveTaskResult> task,
        final List<InsertTaskExecutor> executors){
        task.setResult(Optional.ofNullable(task.getResult()).orElseGet(HashMap::new));
        task.setComplete(false);

        try {
            this.taskDispatcher.dispatchSaveTask(task, executors);
        }finally {
            task.setComplete(true);
        }
    }
}
